Avastage Reacti Context Provider'i tĂ€iustatud mustreid, et tĂ”husalt hallata olekut, optimeerida jĂ”udlust ja vĂ€ltida rakendustes tarbetuid ĂŒmberrenderdusi.
Reacti Context Provider'i mustrid: jĂ”udluse optimeerimine ja ĂŒmberrenderdamise probleemide vĂ€ltimine
Reacti Context API on vĂ”imas tööriist globaalse oleku haldamiseks teie rakendustes. See vĂ”imaldab jagada andmeid komponentide vahel, ilma et peaksite igal tasandil kĂ€sitsi prop'e edasi andma. Kuid Contexti vale kasutamine vĂ”ib pĂ”hjustada jĂ”udlusprobleeme, eriti tarbetuid ĂŒmberrenderdusi. See artikkel uurib erinevaid Context Provider'i mustreid, mis aitavad teil jĂ”udlust optimeerida ja neid lĂ”kse vĂ€ltida.
Probleemi mĂ”istmine: tarbetud ĂŒmberrenderdused
Vaikimisi, kui Contexti vÀÀrtus muutub, renderdatakse uuesti kÔik komponendid, mis seda Contexti kasutavad, isegi kui need ei sÔltu konkreetsest Contexti osast, mis muutus. See vÔib olla mÀrkimisvÀÀrne jÔudluse kitsaskoht, eriti suurtes ja keerukates rakendustes. Kujutage ette stsenaariumi, kus teil on Context, mis sisaldab kasutajateavet, teema seadeid ja rakenduse eelistusi. Kui muutub ainult teema seade, peaksid ideaalis uuesti renderdama ainult teemaga seotud komponendid, mitte kogu rakendus.
Illustreerimiseks kujutage ette globaalset e-kaubanduse rakendust, mis on kĂ€ttesaadav mitmes riigis. Kui valuuta eelistus muutub (mida hallatakse Contexti kaudu), ei tahaks te, et kogu tootekataloog uuesti renderdataks â vĂ€rskendamist vajavad ainult hinna kuvad.
Muster 1: VÀÀrtuse memoisatsioon useMemo
abil
Lihtsaim lĂ€henemine tarbetute ĂŒmberrenderduste vĂ€ltimiseks on Contexti vÀÀrtuse memoisatsioon useMemo
abil. See tagab, et Contexti vÀÀrtus muutub ainult siis, kui selle sÔltuvused muutuvad.
NĂ€ide:
Oletame, et meil on `UserContext`, mis pakub kasutajaandmeid ja funktsiooni kasutaja profiili uuendamiseks.
import React, { createContext, useState, useMemo } from 'react';
const UserContext = createContext(null);
function UserProvider({ children }) {
const [user, setUser] = useState({
name: 'John Doe',
email: 'john.doe@example.com',
location: 'New York, USA'
});
const updateUser = (newUserData) => {
setUser(prevState => ({ ...prevState, ...newUserData }));
};
const contextValue = useMemo(() => ({
user,
updateUser,
}), [user, setUser]);
return (
{children}
);
}
export { UserContext, UserProvider };
Selles nÀites tagab useMemo
, et `contextValue` muutub ainult siis, kui `user` olek vÔi `setUser` funktsioon muutub. Kui kumbki ei muutu, siis `UserContext`'i tarbivaid komponente uuesti ei renderdata.
Eelised:
- Lihtne rakendada.
- Hoiab Ă€ra ĂŒmberrenderdused, kui Contexti vÀÀrtus tegelikult ei muutu.
Puudused:
- Renderdab siiski uuesti, kui mistahes osa kasutaja objektist muutub, isegi kui tarbiv komponent vajab ainult kasutaja nime.
- VÔib muutuda keeruliseks hallata, kui Contexti vÀÀrtusel on palju sÔltuvusi.
Muster 2: Ălesannete eraldamine mitme Contextiga
Granulaarsem lĂ€henemine on jagada oma Context mitmeks vĂ€iksemaks Contextiks, millest igaĂŒks vastutab konkreetse olekuosa eest. See vĂ€hendab ĂŒmberrenderduste ulatust ja tagab, et komponendid renderdatakse uuesti ainult siis, kui nende sĂ”ltuvad andmed muutuvad.
NĂ€ide:
Ăhe `UserContext`'i asemel saame luua eraldi kontekstid kasutajaandmete ja kasutajaeelistuste jaoks.
import React, { createContext, useState } from 'react';
const UserDataContext = createContext(null);
const UserPreferencesContext = createContext(null);
function UserDataProvider({ children }) {
const [user, setUser] = useState({
name: 'John Doe',
email: 'john.doe@example.com',
location: 'New York, USA'
});
const updateUser = (newUserData) => {
setUser(prevState => ({ ...prevState, ...newUserData }));
};
return (
{children}
);
}
function UserPreferencesProvider({ children }) {
const [theme, setTheme] = useState('light');
const [language, setLanguage] = useState('en');
const toggleTheme = () => {
setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
};
return (
{children}
);
}
export { UserDataContext, UserDataProvider, UserPreferencesContext, UserPreferencesProvider };
NĂŒĂŒd saavad komponendid, mis vajavad ainult kasutajaandmeid, tarbida `UserDataContext`'i ja komponendid, mis vajavad ainult teema seadeid, saavad tarbida `UserPreferencesContext`'i. Teema muutused ei pĂ”hjusta enam `UserDataContext`'i tarbivate komponentide ĂŒmberrenderdamist ja vastupidi.
Eelised:
- VĂ€hendab tarbetuid ĂŒmberrenderdusi, eraldades olekumuutused.
- Parandab koodi organiseeritust ja hooldatavust.
Puudused:
- VÔib viia keerukamate komponendihierarhiateni mitme provider'iga.
- NÔuab hoolikat planeerimist, et otsustada, kuidas Contexti jagada.
Muster 3: Selektorfunktsioonid kohandatud hook'idega
See muster hÔlmab kohandatud hook'ide loomist, mis eraldavad Contexti vÀÀrtusest konkreetsed osad ja renderdavad uuesti ainult siis, kui need konkreetsed osad muutuvad. See on eriti kasulik, kui teil on suur Contexti vÀÀrtus paljude omadustega, kuid komponent vajab neist vaid mÔnda.
NĂ€ide:
Kasutades algset `UserContext`'i, saame luua kohandatud hook'e konkreetsete kasutajaomaduste valimiseks.
import React, { useContext } from 'react';
import { UserContext } from './UserContext'; // Eeldusel, et UserContext on failis UserContext.js
function useUserName() {
const { user } = useContext(UserContext);
return user.name;
}
function useUserEmail() {
const { user } = useContext(UserContext);
return user.email;
}
export { useUserName, useUserEmail };
NĂŒĂŒd saab komponent kasutada `useUserName`'i, et renderdada uuesti ainult siis, kui kasutaja nimi muutub, ja `useUserEmail`'i, et renderdada uuesti ainult siis, kui kasutaja e-posti aadress muutub. Muudatused teistes kasutajaomadustes (nt asukoht) ei kĂ€ivita ĂŒmberrenderdusi.
import React from 'react';
import { useUserName, useUserEmail } from './UserHooks';
function UserProfile() {
const name = useUserName();
const email = useUserEmail();
return (
Name: {name}
Email: {email}
);
}
Eelised:
- Peeneteraline kontroll ĂŒmberrenderduste ĂŒle.
- VĂ€hendab tarbetuid ĂŒmberrenderdusi, tellides ainult konkreetsed Contexti vÀÀrtuse osad.
Puudused:
- NÔuab kohandatud hook'ide kirjutamist iga omaduse jaoks, mida soovite valida.
- VÔib tekitada rohkem koodi, kui teil on palju omadusi.
Muster 4: Komponendi memoisatsioon React.memo
abil
React.memo
on kÔrgema jÀrgu komponent (HOC), mis memoiseerib funktsionaalse komponendi. See takistab komponendi uuesti renderdamist, kui selle prop'id pole muutunud. Saate seda kombineerida Contextiga, et jÔudlust veelgi optimeerida.
NĂ€ide:
Oletame, et meil on komponent, mis kuvab kasutaja nime.
import React, { useContext } from 'react';
import { UserContext } from './UserContext';
function UserName() {
const { user } = useContext(UserContext);
return Name: {user.name}
;
}
export default React.memo(UserName);
MĂ€hkides `UserName`'i `React.memo`'ga, renderdatakse see uuesti ainult siis, kui `user` prop (mis edastatakse kaudselt Contexti kaudu) muutub. Selles lihtsustatud nĂ€ites ei takista `React.memo` aga ĂŒksi ĂŒmberrenderdusi, sest kogu `user` objekt edastatakse endiselt prop'ina. Et see oleks tĂ”eliselt tĂ”hus, peate seda kombineerima selektorfunktsioonide vĂ”i eraldi kontekstidega.
TĂ”husam nĂ€ide ĂŒhendab `React.memo` selektorfunktsioonidega:
import React from 'react';
import { useUserName } from './UserHooks';
function UserName() {
const name = useUserName();
return Name: {name}
;
}
function areEqual(prevProps, nextProps) {
// Kohandatud vÔrdlusfunktsioon
return prevProps.name === nextProps.name;
}
export default React.memo(UserName, areEqual);
Siin on `areEqual` kohandatud vÔrdlusfunktsioon, mis kontrollib, kas `name` prop on muutunud. Kui see pole muutunud, siis komponenti uuesti ei renderdata.
Eelised:
- Hoiab Ă€ra ĂŒmberrenderdused, mis pĂ”hinevad prop'ide muutustel.
- VÔib oluliselt parandada puhtalt funktsionaalsete komponentide jÔudlust.
Puudused:
- NÔuab prop'ide muutuste hoolikat kaalumist.
- VÔib olla vÀhem tÔhus, kui komponent saab sageli muutuvaid prop'e.
- Vaikimisi prop'ide vÔrdlus on pinnapealne; vÔib keerukate objektide jaoks vajada kohandatud vÔrdlusfunktsiooni.
Muster 5: Contexti ja reducer'ite (useReducer) kombineerimine
Contexti kombineerimine useReducer
'iga vĂ”imaldab hallata keerukat olekuloogikat ja optimeerida ĂŒmberrenderdusi. useReducer
pakub ettearvatavat olekuhalduse mustrit ja vÔimaldab teil uuendada olekut toimingute alusel, vÀhendades vajadust edastada mitut seadistamisfunktsiooni lÀbi Contexti.
NĂ€ide:
import React, { createContext, useReducer, useContext } from 'react';
const UserContext = createContext(null);
const initialState = {
user: {
name: 'John Doe',
email: 'john.doe@example.com',
location: 'New York, USA'
},
theme: 'light',
language: 'en'
};
const reducer = (state, action) => {
switch (action.type) {
case 'UPDATE_USER':
return { ...state, user: { ...state.user, ...action.payload } };
case 'TOGGLE_THEME':
return { ...state, theme: state.theme === 'light' ? 'dark' : 'light' };
case 'SET_LANGUAGE':
return { ...state, language: action.payload };
default:
return state;
}
};
function UserProvider({ children }) {
const [state, dispatch] = useReducer(reducer, initialState);
return (
{children}
);
}
function useUserState() {
const { state } = useContext(UserContext);
return state.user;
}
function useUserDispatch() {
const { dispatch } = useContext(UserContext);
return dispatch;
}
export { UserContext, UserProvider, useUserState, useUserDispatch };
NĂŒĂŒd saavad komponendid olekule juurde pÀÀseda ja toiminguid saata, kasutades kohandatud hook'e. NĂ€iteks:
import React from 'react';
import { useUserState, useUserDispatch } from './UserContext';
function UserProfile() {
const user = useUserState();
const dispatch = useUserDispatch();
const handleUpdateName = (e) => {
dispatch({ type: 'UPDATE_USER', payload: { name: e.target.value } });
};
return (
Name: {user.name}
);
}
See muster edendab struktureeritumat lÀhenemist olekuhaldusele ja vÔib lihtsustada keerulist Contexti loogikat.
Eelised:
- Tsentraliseeritud olekuhaldus ettearvatavate uuendustega.
- VÀhendab vajadust edastada mitut seadistamisfunktsiooni lÀbi Contexti.
- Parandab koodi organiseeritust ja hooldatavust.
Puudused:
- NÔuab
useReducer
hook'i ja reducer-funktsioonide mÔistmist. - VÔib olla liiga keeruline lihtsate olekuhalduse stsenaariumide jaoks.
Muster 6: Optimistlikud uuendused
Optimistlikud uuendused hÔlmavad kasutajaliidese kohest uuendamist nii, nagu oleks toiming Ônnestunud, isegi enne kui server seda kinnitab. See vÔib oluliselt parandada kasutajakogemust, eriti suure latentsusega olukordades. Siiski nÔuab see vÔimalike vigade hoolikat kÀsitlemist.
NĂ€ide:
Kujutage ette rakendust, kus kasutajad saavad postitusi meeldivaks mĂ€rkida. Optimistlik uuendus suurendaks kohe meeldimiste arvu, kui kasutaja klĂ”psab meeldimisnupul, ja seejĂ€rel tĂŒhistaks muudatuse, kui serveripĂ€ring ebaĂ”nnestub.
import React, { useContext, useState } from 'react';
import { UserContext } from './UserContext';
function LikeButton({ postId }) {
const { dispatch } = useContext(UserContext);
const [isLiking, setIsLiking] = useState(false);
const handleLike = async () => {
setIsLiking(true);
// Uuenda meeldimiste arvu optimistlikult
dispatch({ type: 'INCREMENT_LIKES', payload: { postId } });
try {
// Simuleeri API-kÔnet
await new Promise(resolve => setTimeout(resolve, 500));
// Kui API-kÔne Ônnestub, Àra tee midagi (kasutajaliides on juba uuendatud)
} catch (error) {
// Kui API-kĂ”ne ebaĂ”nnestub, tĂŒhista optimistlik uuendus
dispatch({ type: 'DECREMENT_LIKES', payload: { postId } });
alert('Postituse meeldivaks mÀrkimine ebaÔnnestus. Palun proovige uuesti.');
} finally {
setIsLiking(false);
}
};
return (
);
}
Selles nĂ€ites saadetakse `INCREMENT_LIKES` toiming kohe ja seejĂ€rel tĂŒhistatakse, kui API-kĂ”ne ebaĂ”nnestub. See pakub reageerivamat kasutajakogemust.
Eelised:
- Parandab kasutajakogemust, pakkudes kohest tagasisidet.
- VĂ€hendab tajutavat latentsust.
Puudused:
- NĂ”uab hoolikat veakĂ€sitlust optimistlike uuenduste tĂŒhistamiseks.
- VÔib pÔhjustada vastuolusid, kui vigu ei kÀsitleta Ôigesti.
Ăige mustri valimine
Parim Context Provider'i muster sÔltub teie rakenduse konkreetsetest vajadustest. Siin on kokkuvÔte, mis aitab teil valida:
- VÀÀrtuse memoisatsioon
useMemo
abil: Sobib lihtsate Contexti vÀÀrtuste jaoks, millel on vĂ€he sĂ”ltuvusi. - Ălesannete eraldamine mitme Contextiga: Ideaalne, kui teie Context sisaldab omavahel mitteseotud olekuosi.
- Selektorfunktsioonid kohandatud hook'idega: Parim suurte Contexti vÀÀrtuste jaoks, kus komponendid vajavad vaid mÔnda omadust.
- Komponendi memoisatsioon
React.memo
abil: TÔhus puhtalt funktsionaalsete komponentide jaoks, mis saavad prop'e Contextist. - Contexti ja reducer'ite (
useReducer
) kombineerimine: Sobib keeruka olekuloogika ja tsentraliseeritud olekuhalduse jaoks. - Optimistlikud uuendused: Kasulik kasutajakogemuse parandamiseks suure latentsusega stsenaariumides, kuid nÔuab hoolikat veakÀsitlust.
TÀiendavad nÀpunÀited Contexti jÔudluse optimeerimiseks
- VÀltige tarbetuid Contexti uuendusi: Uuendage Contexti vÀÀrtust ainult siis, kui see on vajalik.
- Kasutage muutumatuid andmestruktuure: Muutmatus aitab Reactil muutusi tÔhusamalt tuvastada.
- Profileerige oma rakendust: Kasutage React DevTools'i jÔudluse kitsaskohtade tuvastamiseks.
- Kaaluge alternatiivseid olekuhalduslahendusi: VÀga suurte ja keerukate rakenduste jaoks kaaluge tÀiustatud olekuhaldusraamatukogusid nagu Redux, Zustand vÔi Jotai.
KokkuvÔte
Reacti Context API on vĂ”imas tööriist, kuid jĂ”udlusprobleemide vĂ€ltimiseks on oluline seda Ă”igesti kasutada. MĂ”istes ja rakendades selles artiklis kĂ€sitletud Context Provider'i mustreid, saate tĂ”husalt hallata olekut, optimeerida jĂ”udlust ja ehitada tĂ”husamaid ja reageerivamaid Reacti rakendusi. Pidage meeles, et analĂŒĂŒsige oma konkreetseid vajadusi ja valige muster, mis sobib teie rakenduse nĂ”uetega kĂ”ige paremini.
Globaalset perspektiivi arvestades peaksid arendajad tagama ka selle, et olekuhalduse lahendused töötaksid sujuvalt erinevates ajavööndites, valuutavormingutes ja piirkondlikes andmenĂ”uetes. NĂ€iteks Contextis olev kuupĂ€eva vormindamise funktsioon peaks olema lokaliseeritud vastavalt kasutaja eelistusele vĂ”i asukohale, tagades ĂŒhtlase ja tĂ€pse kuupĂ€eva kuvamise olenemata sellest, kust kasutaja rakendusele ligi pÀÀseb.